package com.MyApp.CompanyRank;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.LineNumberReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import au.com.bytecode.opencsv.*;

public class UnivRanking {

    public static String dataDir = "rankingdata";
    public static String globalFileName = dataDir + File.separator + "GlobalList.txt";
    public static String cnFileName = dataDir + File.separator + "GlobalListcn.txt";

    public static String overallGlobalFile = dataDir + File.separator + "OverallGlobal" + ".csv";
    // 学校引用数
    public static String UniversityTwitterFile = dataDir + File.separator + "UniversityTwitter.csv";
    // twitter  fans num
   
    // public static String almaMaterFilename = "peopleranking" +
    // File.separator+"AlmamaterConsolidatedList.csv"; //by ider
    public static String almaMaterFilename = dataDir + File.separator + "peopleranking" + File.separator
            + "AlmamaterConsolidatedList.csv";
    

           
    
    // 学校　师生比例

    public static DBpediaTable collegeTable;

    static DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");

    static String getTimeNow() {
        return dateFormat.format(new Date());
    }

    public UnivRanking() {

    }

    /***
     * maxAlmaMater maxAverageEndowment maxFacultyStudentRatio
     * 
     * averageEndowment facultyStudentRatio
     * 
     * @param args
     * @throws Exception
     */
    public static void main(String args[]) throws Exception {
        
        String MicOverallFilename = dataDir + File.separator + "MicOverall.csv";  //论文总数
        String Mic10yearsCountFilename = dataDir + File.separator + "Mic10yearsCount.csv";        //10年论文总数
        String MicReferenceCountFilename = dataDir + File.separator + "1001ReferenceCount.csv";   //论文总的被引用数
        String MicReferenceCount10YeatsFilename  = dataDir + File.separator + "1001ReferenceCount10year.csv"; //论文10年被引用数 
        

        System.out.println("starting University Ranking...");
        System.out.println("retrieving school list ...");

        File f = new File(globalFileName);
        File cnf = new File(cnFileName);
        // if file doesnt exists, then exit
        if (!f.exists() || !cnf.exists()) {
            System.err.println("The file " + globalFileName + " does not exist!");
            System.exit(1);
        }

        String filename = dataDir + File.separator + "EducationalInstitution.csv";
        // 未知作用

        System.out.println("reading EducationInstitution list ...");
        collegeTable = // new DBpediaTable(wikiDB, new InputStreamReader(new
                       // FileInputStream(filename), "UTF-8"));
        new DBpediaTable(new InputStreamReader(new FileInputStream(filename), "UTF-8"));
        // 读取name 对应的 属性
        
        HashMap<String, Double> almaMaterMap = new HashMap<String, Double>();
        // 生成name：row[1]的 almaMaterMap
        
        HashMap<String, Long> MasOverall = new HashMap<String, Long>();
        // mas总引用数 
        Long maxMasOverall = getMicOverallMax(MicOverallFilename,MasOverall);
 
        HashMap<String, Long> Mic10yearsCount = new HashMap<String, Long>();
        // mas10年论文总引用数 
        Long maxMic10yearsCount = getMic10yearsCount(Mic10yearsCountFilename,Mic10yearsCount);

        HashMap<String, Long>  MicReferenceCount = new HashMap<String, Long>();
        // mas论文总引用数 
        Long maxMicReferenceCount = getMicReferenceCount(MicReferenceCountFilename,MicReferenceCount);
        
        HashMap<String, Long>  MicReferenceCount10YeatsCount = new HashMap<String, Long>();
        // mas论文总引用数 
        Long maxMicReferenceCount10YeatsCount = getMicReferenceCount(MicReferenceCount10YeatsFilename,MicReferenceCount10YeatsCount);
        
        
        
        System.out.println("reading AlmaMater list ...");
        double almaMaterMax = readAlmaMaterFile(almaMaterFilename, almaMaterMap);
        // almaMaterMax Max almaMater

        ArrayList<UnivEntry> globalList = parseList();
        // 获得 name:score entity List
        long maxScore = globalList.get(2).score;
        System.out.println("The max inlink school is " + globalList.get(0).schoolName + " with "
                + globalList.get(0).score);
        System.out.println("The second largest inlink school is " + globalList.get(1).schoolName + " with "
                + globalList.get(1).score);
        System.out.println("The third largest inlink school is " + globalList.get(2).schoolName + " with "
                + globalList.get(2).score);
        
        HashMap<String,Long> UniversityTwitter = new HashMap<String,Long>();
        getUniversityTwitter(UniversityTwitterFile, UniversityTwitter);     
        Collections.sort(globalList, new UniversityTwitterFansComparator(UniversityTwitter));
        for (int i = 0; i < 3; i++) {
            System.out.println("The number " + (i + 1) + " UniversityTwitterFans school is " + globalList.get(i).schoolName
                    + " with " +UniversityTwitter.get(globalList.get(i).schoolName));
        }
        Long maxtwitterfans = UniversityTwitter.get(globalList.get(2).schoolName);
        Collections.sort(globalList, new UniversityTwitterFansRadioComparator(UniversityTwitter));
        for (int i = 0; i < 3; i++) {
            System.out.println("The number " + (i + 1) + " UniversityTwitterFansRadio school is " + globalList.get(i).schoolName
                    + " with " + getRadio(UniversityTwitter.get(globalList.get(i).schoolName), globalList.get(i).schoolName));
        }
        Double maxtwitterfansradio = getRadio(UniversityTwitter.get(globalList.get(2).schoolName), globalList.get(2).schoolName);
        //twitter fans
        
        Collections.sort(globalList, new AlmaMaterComparator(almaMaterMap));
        // 根据 AlmaMater 实现一个排序，globalList，有序List
        Double maxAlmaMater = almaMaterMap.get(globalList.get(2).schoolName);
        
        System.out.println("The max almamter influence school is " + globalList.get(0).schoolName + " with "
                + almaMaterMap.get(globalList.get(0).schoolName));
        System.out.println("The second largest almamter influence school is " + globalList.get(1).schoolName + " with "
                + almaMaterMap.get(globalList.get(1).schoolName));
        System.out.println("The third largest almamter influence school is " + globalList.get(2).schoolName + " with "
                + almaMaterMap.get(globalList.get(2).schoolName));
        
        Collections.sort(globalList, new AlmaMaterRadioComparator(almaMaterMap));
        // 根据 AlmaMater 实现一个排序，globalList，有序List
        Double maxAlmaMaterRadio = getRadio(almaMaterMap.get(globalList.get(2).schoolName),globalList.get(2).schoolName);
        for (int i = 0; i < 3; i++) {
            System.out.println("The number " + (i + 1) + " AlmaMaterRadio school is " + globalList.get(i).schoolName
                    + " with " +getRadio(almaMaterMap.get(globalList.get(i).schoolName),globalList.get(i).schoolName));
        }
        
        Collections.sort(globalList, new EndowmentComparator(collegeTable));
        // 根据其捐助进行排名
        double maxAverageEndowment = getAverageEndowment(collegeTable, globalList.get(3).schoolName);
        Double maxEndowment = getEndowment(collegeTable, globalList.get(3).schoolName);
        for (int i = 0; i < 3; i++) {
            System.out.println("The number " + (i + 1) + " average endowment school is " + globalList.get(i).schoolName
                    + " with " + getAverageEndowment(collegeTable, globalList.get(i).schoolName) + " per student");
        }

        Collections.sort(globalList, new FacultyStudentRatioComparator(collegeTable));
        // 师生比例 排序
        double maxFacultyStudentRatio = getFacultyStudentRatio(collegeTable, globalList.get(2).schoolName);
        System.out.println("The max faculty/student school is " + globalList.get(0).schoolName + " with "
                + getFacultyStudentRatio(collegeTable, globalList.get(0).schoolName));
        System.out.println("The second faculty/student school is " + globalList.get(1).schoolName + " with "
                + getFacultyStudentRatio(collegeTable, globalList.get(1).schoolName));
        System.out.println("The third faculty/student school is " + globalList.get(2).schoolName + " with "
                + getFacultyStudentRatio(collegeTable, globalList.get(2).schoolName));

     

        UnivEntry[] sorted = new UnivEntry[globalList.size()];
        OutUnivEntry[] univList = new OutUnivEntry[globalList.size()];
        // added by ider
        for (int i = 0; i < sorted.length; i++) {
            sorted[i] = globalList.get(i);
            univList[i] = new OutUnivEntry(sorted[i].schoolName, sorted[i].chineseName, sorted[i].score);

            String schoolname = sorted[i].schoolName;

            if(schoolname.equals("Soka University of America"))
                System.out.println("Soka University of America");
            long inlinkScore = sorted[i].score;
           

            // third largest score
            if (inlinkScore > maxScore)
                inlinkScore = maxScore;
           
            long maxMasLink = maxMasOverall;
//            System.out.println(schoolname);
            long MasLink = MasOverall.get(schoolname);
            
            
//            Double averageinlinkScor = getAverageinlinkScore(inlinkScore, schoolname);
//            Double averagemaxScore = getAverageinlinkScore(maxScore, globalList.get(2).schoolName);
//            if(averageinlinkScor>averagemaxScore)
//                averageinlinkScor = averagemaxScore;
            
            Double almaMater = almaMaterMap.get(schoolname);
            
            if (almaMater == null) {
                almaMater = (double) 0.0;
                System.out.println("The school " + sorted[i].schoolName + " does not have almamater in record");
            }
            if (almaMater > maxAlmaMater)
                almaMater = maxAlmaMater;

            
            double averageEndowment = getAverageEndowment(collegeTable, schoolname);
            if (averageEndowment > maxAverageEndowment)
                averageEndowment = maxAverageEndowment;
            
           
            Double endowment= getEndowment(collegeTable, schoolname);
            if(endowment>maxEndowment)
                endowment = maxEndowment;

            Long twitternum = UniversityTwitter.get(schoolname);
            if(twitternum>maxtwitterfans)
                twitternum = maxtwitterfans;
            
            Double twitternumRadio = getRadio(twitternum, schoolname);
            if(twitternumRadio>maxtwitterfansradio)
                twitternumRadio = maxtwitterfansradio;

            double facultyStudentRatio = getFacultyStudentRatio(collegeTable, schoolname);
            if (facultyStudentRatio > maxFacultyStudentRatio)
                facultyStudentRatio = maxFacultyStudentRatio;
            
            Double almaMaterRadio = getRadio(almaMaterMap.get(schoolname),schoolname);
            if (almaMaterRadio > maxAlmaMaterRadio)
                almaMaterRadio = maxAlmaMaterRadio;

            /*********************************************************************************************************/
            /***
             * inlinkScore,maxScore ,almaMater,almaMaterMax 母校引用数
             * averageEndowment maxAverageEndowment 平均资金 facultyStudentRatio
             * maxFacultyStudentRatio师生比例
             */

            double sc = 0.0;
            univList[i].masReferenceCount10YeatsCount = MicReferenceCount10YeatsCount.get(schoolname) *100000 /maxMicReferenceCount10YeatsCount;
            /*---------------------------------------------------------------------------------------------------*/
            univList[i].masReferenceCount = MicReferenceCount.get(schoolname) *100000 /maxMicReferenceCount;
            /*---------------------------------------------------------------------------------------------------*/
            univList[i].twitternum = (long)(twitternum*100000/maxtwitterfans);
            univList[i].twitterStudentRatio = (long)(twitternumRadio*100000/maxtwitterfansradio);
            /*---------------------------------------------------------------------------------------------------*/
            
            univList[i].maclast10yearslink = (long)(Mic10yearsCount.get(schoolname) *100000 /maxMic10yearsCount);
            /*---------------------------------------------------------------------------------------------------*/
            univList[i].maslink = (long)(MasLink * 100000) / maxMasLink;

            /*---------------------------------------------------------------------------------------------------*/
                
            /*---------------------------------------------------------------------------------------------------*/
            univList[i].endowment = (long) (endowment * 100000 / maxEndowment);
            
            /*---------------------------------------------------------------------------------------------------*/
            sc = (inlinkScore * 100000 / maxScore) * 0.80 + (almaMater * 100000 / almaMaterMax) * 0.20;

            univList[i].inlinkScore =(long) ( inlinkScore * 100000 / maxScore);

             
            univList[i].almaMaterRadio = (long)(almaMaterRadio*100000/maxAlmaMaterRadio);
            univList[i].almaMater = (long) (almaMater * 100000 / almaMaterMax); 
            /*-----------------------------------inlinkScore almaMater----------------------------------------------------------------*/
            if (averageEndowment > 0.0) {
                sc += ((averageEndowment * 100000 / maxAverageEndowment) * 0.2 - (inlinkScore * 100000 / maxScore) * 0.2);
                univList[i].averageEndowment = (long) (averageEndowment * 100000 / maxAverageEndowment); 
            } else { // if there is no endowment, minus some percentage
                sc -= (inlinkScore * 100000 / maxScore) * 0.125;
                univList[i].averageEndowment = 0; 
            }
            /*------------------------------------------averageEndowment---------------------------------------------------------*/
            if (facultyStudentRatio > 0.0) {
                sc += ((facultyStudentRatio * 100000 / maxFacultyStudentRatio) * 0.05 - (inlinkScore * 100000 / maxScore) * 0.05);
                univList[i].facultyStudentRatio = (long) (facultyStudentRatio * 100000 / maxFacultyStudentRatio); 
            } else {
                univList[i].facultyStudentRatio = 0; 
            }
            /*-------------------------------------------facultyStudentRatio--------------------------------------------------------*/
            sorted[i].score = (int) sc;

            /*********************************************************************************************************/

        }
        Arrays.sort(sorted);
        String sortedFile = dataDir + File.separator + "OverallRankingDepth" + UniversityData.depth + ".csv";
        printRankingData(sorted, sortedFile);
        printOutUnivEntry(univList, "mydata.csv");
        printOutUnivEntry_cn(univList, "mydata_cn.csv");
    }

    public static int getInt(String str) {
        if (str == null || str.equals("NULL"))
            return 0;
        try {
            return Integer.valueOf(str);
        } catch (NumberFormatException nfe) {
            if (str.startsWith("{") && str.endsWith("}")) {
                String str1 = str.substring(1, (str.length() - 1));
                if (str1.contains("|")) {
                    String str2 = str1.substring(str1.lastIndexOf("|") + 1);
                    try {
                        return Integer.valueOf(str2);
                    } catch (NumberFormatException nfe2) {
                        return 0;
                    }
                } else {
                    try {
                        return Integer.valueOf(str1);
                    } catch (NumberFormatException nfe2) {
                        return 0;
                    }
                }
            }
            return 0;
        }
    }

    
    
    public static int getTotalStudentNumber(DBpediaTable db, String schoolname) {
        // XXX
//        System.out.println(schoolname);
        if (schoolname.equals("Rockefeller University")) return 225;
        if(schoolname.equals("University of California, Berkeley")) return 37581;
        if(schoolname.equals("University of California, Los Angeles")) return 43301;
        
        int studentNumber = getInt(db.getValue(schoolname, "numberOfStudents"));
        
 
        int undergraduateStudentNumber = getInt(db.getValue(schoolname, "numberOfUndergraduateStudents"));
        int postgraduateStudentNumber = getInt(db.getValue(schoolname, "numberOfPostgraduateStudents"));
        
        
//        System.out.println("studentNumber:"+studentNumber);
        
        if (studentNumber == 0)
            studentNumber = undergraduateStudentNumber + postgraduateStudentNumber;
        if (studentNumber < 25)
            return 0;
        return studentNumber;

    }

    public static double getFacultyStudentRatio(DBpediaTable db, String schoolname) {
        // XXX some exception, noise data need to be filtered
        if (schoolname.equals("Tianjin Medical University"))
            return 0.0;

        String pv = collegeTable.getValue(schoolname, "facultySize");
        
        String ne = getExcfacultySize(schoolname);
        if (ne != null){
           pv = ne;
        }
        
        if (pv == null || pv.equals("NULL"))
            return 0.0;
        if (pv.startsWith("{")) {
            String[] pvs = collegeTable.getValues(schoolname, "facultySize");
            if (pvs != null)
                pv = pvs[0];
        }
        
        double fn = 0.0;
        try {
            fn = Double.valueOf(pv);
        } catch (NumberFormatException nfe) {
            System.out.println(schoolname + " " + pv);
            fn = 0.0;
        }

        if (fn == 0.0)
            return 0.0;

        int studentNumber = getTotalStudentNumber(collegeTable, schoolname);


        if (studentNumber == 0)
            return 0.0;

        return (fn / studentNumber);
    }
    
    
    public static String getExcfacultySize(String schoolname) {
//        System.out.println("facultySize:"+schoolname);
        if(schoolname.equals("University of Oxford")) return "11804";
        if(schoolname.equals("University of Pennsylvania")) return "4318";
        if(schoolname.equals("University of California, Berkeley")) return "2082";
        if(schoolname.equals("University of California, Los Angeles")) return "4016";
        if(schoolname.equals("University College London")) return "4000";
        if(schoolname.equals("University of Edinburgh")) return "4000";
        if(schoolname.equals("University of Hong Kong")) return "14130";
        if(schoolname.equals("University of Melbourne")) return "3720";
        if(schoolname.equals("University of Sydney")) return "2940";
        if(schoolname.equals("Rutgers University")) return "2930";
        if(schoolname.equals("University of Manchester")) return "3849";
        if(schoolname.equals("Emory University")) return "13225";
        if(schoolname.equals("Australian National University")) return "3753";
        if(schoolname.equals("University of Maryland, College Park")) return "4250";
        if(schoolname.equals("York University")) return "7000";
        if(schoolname.equals("Moscow State University")) return "5000";
        if(schoolname.equals("Imperial College London")) return "3692";
        if(schoolname.equals("University of California, San Diego")) return "1215";
        if(schoolname.equals("University of Birmingham")) return "6000";
        if(schoolname.equals("University of Glasgow")) return "2942";
        if(schoolname.equals("University of Queensland")) return "5250";
        if(schoolname.equals("National Taiwan University")) return "1793";
//        if(schoolname.equals("xxxx")) return "xxxx";
//        if(schoolname.equals("xxxx")) return "xxxx";
        return null;
    }
    public static String getExcEndowment(String schoolname) {
//        System.out.println("Endowment:"+schoolname);
        if(schoolname.equals("University of California, Berkeley")) return "4.045E9";
        if(schoolname.equals("University of California, Los Angeles")) return "3.496E9";
        if(schoolname.equals("University of Tokyo")) return "2.332E10";
        if(schoolname.equals("Tsinghua University")) return "1.5E9";
        if(schoolname.equals("Peking University")) return "2.773E9";
        if(schoolname.equals("Zhejiang University")) return "3.078E9";
        if(schoolname.equals("University of Hong Kong")) return "8.3E8";
        if(schoolname.equals("Weizmann Institute of Science")) return "1E8";
        if(schoolname.equals("University of Missouri")) return "8.328E8";
        if(schoolname.equals("University of North Carolina at Chapel Hill")) return "2.696E9";
        if(schoolname.equals("National University of Singapore")) return "1.79E9";
        if(schoolname.equals("University of Maryland, College Park")) return "8.5E8";
        if(schoolname.equals("Nanjing University")) return "4E8";
        if(schoolname.equals("London School of Economics")) return "1.129E8";
        if(schoolname.equals("University of California, San Diego")) return "951.4E8";
        if(schoolname.equals("Monash University")) return "1.875E9";
        if(schoolname.equals("University of Queensland")) return "1.67E9";
        if(schoolname.equals("University of Göttingen")) return "1.05E9";
        if(schoolname.equals("National Taiwan University")) return "3.1E9";
//        if(schoolname.equals("xxxx")) return "xxxx";
//        if(schoolname.equals("xxxx")) return "xxxx";
//        if(schoolname.equals("xxxx")) return "xxxx";
        return null;
    }
    
    public static double getEndowment(DBpediaTable db, String schoolname) {
        String pv = collegeTable.getValue(schoolname, "endowment");
        double totalEndowment = 0.0;
        
        String ne = getExcEndowment(schoolname);
        if (ne != null){
           pv = ne;
        }
        if (pv == null || pv.equals("NULL"))
            return 0.0;
        pv = DBpediaTable.getLastWikiBag(pv);
        
        double nu;
        try {
            nu = Double.valueOf(pv);
            String sname = schoolname.trim();
            String countryname = collegeTable.getCountryName(sname);
            if (countryname == null || countryname.equals("NULL")) {
                nu = 0.0;
                System.out.println(schoolname + " does not have a country name");
            } else {
                String cr = DBpediaTable.countryName2CurrencyName.get(countryname);
                if (cr == null) {
                    nu = 0.0;
                    System.out.println(countryname + " does not have currency name");
                } else {
                    Double r = DBpediaTable.currencyRateTable.get(cr);
                    if (r == null)
                        nu = 0.0;
                    else
                        nu = nu * r;
                }
            }
        } catch (NumberFormatException nfe) {
//            System.out.println(schoolname + ":" + pv);
            nu = 0.0;
        }
        totalEndowment = nu;
        return totalEndowment ;
    }
    
    public static double getAverageEndowment(DBpediaTable db, String schoolname) {
        String pv = collegeTable.getValue(schoolname, "endowment");
        double totalEndowment = 0.0;
        
        String ne = getExcEndowment(schoolname);
        
       if (ne != null){
           pv = ne;
       }
       
        if (pv == null || pv.equals("NULL"))
            return 0.0;
        pv = DBpediaTable.getLastWikiBag(pv);
        
        double nu;
        try {
            nu = Double.valueOf(pv);
            String sname = schoolname.trim();
            String countryname = collegeTable.getCountryName(sname);
            if (countryname == null || countryname.equals("NULL")) {
                nu = 0.0;
                System.out.println(schoolname + " does not have a country name");
            } else {
                String cr = DBpediaTable.countryName2CurrencyName.get(countryname);
                if (cr == null) {
                    nu = 0.0;
                    System.out.println(countryname + " does not have currency name");
                } else {
                    Double r = DBpediaTable.currencyRateTable.get(cr);
                    if (r == null)
                        nu = 0.0;
                    else
                        nu = nu * r;
                }
            }
        } catch (NumberFormatException nfe) {
//            System.out.println(schoolname + ":" + pv);
            nu = 0.0;
        }
        totalEndowment = nu;

        int studentNumber = getTotalStudentNumber(collegeTable, schoolname);

        if (studentNumber == 0)
            return 0.0;

        return (totalEndowment / studentNumber);
    }

    public static double getRadio(long num, String schoolname) {
       
        int studentNumber = getTotalStudentNumber(collegeTable, schoolname);
        if (studentNumber == 0)
            return 0.0;
        return (num / studentNumber);
    }
    
    public static double getRadio(Double num, String schoolname) {
        if(num==null){
            return 0.0;
        }
        int studentNumber = getTotalStudentNumber(collegeTable, schoolname);
        if (studentNumber == 0)
            return 0.0;
        return (num / studentNumber);
    }
    
    
    public static Long getTwitterRadio2(long twitternum, String schoolname) {
        
        int studentNumber = getTotalStudentNumber(collegeTable, schoolname);
        if (studentNumber == 0)
            return 0L;
        return (twitternum / studentNumber);
    }
    
    /***
     * 读取 twitter fans
     * 
     * @param almaMaterFilename
     * @param almaMaterMap
     * @return
     * @throws IOException
     */
    public static Long getUniversityTwitter(String UniversityTwitterFile, HashMap<String, Long> UniversityTwitter)
            throws IOException {
        File mof = new File(UniversityTwitterFile);
        // if file doesnt exists, then exit
        if (!mof.exists()) {
            System.err.println("The file " + UniversityTwitterFile + " does not exist!");
            System.exit(1);
        }
        Long moMax = 0L;
        Stack<Long> Max = new Stack<Long>();
        CSVReader csvReader = new CSVReader(new InputStreamReader(new FileInputStream(mof), "UTF-8"));
        String[] row;

        while ((row = csvReader.readNext()) != null) {
            Long ac = Long.valueOf(row[0]);
            if (ac > moMax){
                moMax = ac;
                Max.push(moMax);
            }
            UniversityTwitter.put(row[1], ac);
        }
        csvReader.close();
        for(int i = 0 ;i<3;i++){
            moMax =Max.pop();
            if(Max.empty())
                break;
        }
        return moMax;
    }
    

    /***
     * 读取 mis 总引用数
     * 
     * @param almaMaterFilename
     * @param almaMaterMap
     * @return
     * @throws IOException
     */
    public static Long getMicOverallMax(String MicOverallFilename, HashMap<String, Long> MasOverall)
            throws IOException {
        File mof = new File(MicOverallFilename);
        // if file doesnt exists, then exit
        if (!mof.exists()) {
            System.err.println("The file " + MicOverallFilename + " does not exist!");
            System.exit(1);
        }
        Long moMax = 0L;
        Stack<Long> Max = new Stack<Long>();
        CSVReader csvReader = new CSVReader(new InputStreamReader(new FileInputStream(mof), "UTF-8"));
        String[] row;
        // build the <schoolName, almaMater Sum Count> map and also find the max
        // almamater sum count
        while ((row = csvReader.readNext()) != null) {
            Long ac = Long.valueOf(row[1]);
            if (ac > moMax){
                moMax = ac;
                Max.push(moMax);
            }
            MasOverall.put(row[0], ac);
        }
        csvReader.close();
        for(int i = 0 ;i<3;i++){
            moMax =Max.pop();
            if(Max.empty())
                break;
        }
        return moMax;
    }

    
    public static Long getMicReferenceCount(String MicReferenceCountFilename, HashMap<String, Long> MasOverall)
            throws IOException {
        File mof = new File(MicReferenceCountFilename);
        // if file doesnt exists, then exit
        if (!mof.exists()) {
            System.err.println("The file " + MicReferenceCountFilename + " does not exist!");
            System.exit(1);
        }
        Long moMax = 0L;
        Stack<Long> Max = new Stack<Long>();
        CSVReader csvReader = new CSVReader(new InputStreamReader(new FileInputStream(mof), "UTF-8"));
        String[] row;
        // build the <schoolName, almaMater Sum Count> map and also find the max
        // almamater sum count
        while ((row = csvReader.readNext()) != null) {
            Long ac = Long.valueOf(row[1]);
          System.out.println("MicReferenceCount:"+ac);
            if (ac > moMax){
                moMax = ac;
                Max.push(moMax);
            }
            MasOverall.put(row[0], ac);
        }
        csvReader.close();
        for(int i = 0 ;i<3;i++){
            moMax =Max.pop();
            if(Max.empty())
                break;
        }
        return moMax;
    }
    
    
    /***
     * 读取 mis 10年 论文总引用数
     * 
     * @param almaMaterFilename
     * @param almaMaterMap
     * @return
     * @throws IOException
     */
    public static Long getMic10yearsCount(String getMic10yearsCountFilename, HashMap<String, Long> MasOverall)
            throws IOException {
        File mof = new File(getMic10yearsCountFilename);
        // if file doesnt exists, then exit
        if (!mof.exists()) {
            System.err.println("The file " + getMic10yearsCountFilename + " does not exist!");
            System.exit(1);
        }
        Long moMax = 0L;
        CSVReader csvReader = new CSVReader(new InputStreamReader(new FileInputStream(mof), "UTF-8"));
        String[] row;
        // build the <schoolName, almaMater Sum Count> map and also find the max
        // almamater sum count
        while ((row = csvReader.readNext()) != null) {
            Long ac = Long.valueOf(row[1]);
            if (ac > moMax)
                moMax = ac;
            MasOverall.put(row[0], ac);
        }
        csvReader.close();
        return moMax;
    }
    
    
    /***
     * 读取 AlmamaterConsolidatedList 生成name：row[1]的 almaMaterMap 并返回最大的row[1]
     * 
     * @param almaMaterFilename
     * @param almaMaterMap
     * @return
     * @throws IOException
     */
    public static double readAlmaMaterFile(String almaMaterFilename, HashMap<String, Double> almaMaterMap)
            throws IOException {
        File amf = new File(almaMaterFilename);
        // if file doesnt exists, then exit
        if (!amf.exists()) {
            System.err.println("The file " + almaMaterFilename + " does not exist!");
            System.exit(1);
        }
        double almaMaterMax = 0.0;
        CSVReader csvReader = new CSVReader(new InputStreamReader(new FileInputStream(amf), "UTF-8"));
        String[] row;
        // build the <schoolName, almaMater Sum Count> map and also find the max
        // almamater sum count
        while ((row = csvReader.readNext()) != null) {
            double ac = Double.valueOf(row[1]);
            if (ac > almaMaterMax)
                almaMaterMax = ac;
            almaMaterMap.put(row[0], ac);
        }
        csvReader.close();
        return almaMaterMax;
    }

    /**
     * print a sorted list to a csv file
     * 
     * @param ulist
     *            a sorted list
     * @param outFile
     * @throws IOException
     */
    static void printRankingData(UnivEntry[] ulist, String outFile) throws IOException {
        OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8");
        float maxScore = ulist[0].score;
        for (int i = 0; i < ulist.length; i++) {
            int ranking = i + 1;
            int cur = i;
            while (true) {
                if (cur == 0 || ulist[cur].score != ulist[cur - 1].score) {
                    ranking = cur + 1;
                    break;
                }
                cur--;
            }
            double normalizedScore = 0.0;
            if (ulist[i].score > 0)
                normalizedScore = (Math.log1p(ulist[i].score) * 100) / Math.log1p(maxScore);

            BigDecimal bd = new BigDecimal(normalizedScore);
            bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
            normalizedScore = bd.doubleValue();

            fw.write(ranking + "," + "\"" + ulist[i].schoolName + "\"" // +
                                                                       // ",\""
                                                                       // +ulist[i].chineseName+"\""
                    + "," + normalizedScore + "," + ulist[i].score + "\n");
        }
        fw.close();
    }

    /**
     * print to a csv file
     * 
     * @param OutUnivEntry
     *            the basic data
     * @param outFile
     * @throws IOException
     */
    static void printOutUnivEntry(OutUnivEntry[] ulist, String outFile) throws IOException {
        OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8");
        fw.write("schoolName,Reputation,Productivity,EducationQualit,FinancialSupport,AcademicCapability");
        for (int i = 0; i < ulist.length; i++) {
            ulist[i].calculate();
            fw.write("\n" + "\"" + ulist[i].schoolName + "\"" + "," + ulist[i].Reputation + "," + ulist[i].Productivity + "," + ulist[i].EducationQualit
                    + "," + ulist[i].FinancialSupport + "," + ulist[i].AcademicCapability );
        }
        fw.close();
    }
    
    static void printOutUnivEntry_cn(OutUnivEntry[] ulist, String outFile) throws IOException {
        OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8");
        fw.write("schoolName,Reputation,Productivity,EducationQualit,FinancialSupport,AcademicCapability,chinesename");
        for (int i = 0; i < ulist.length; i++) {
            ulist[i].calculate();
            fw.write("\n" + "\"" + ulist[i].schoolName + "\"" + "," + ulist[i].Reputation + "," + ulist[i].Productivity + "," + ulist[i].EducationQualit
                    + "," + ulist[i].FinancialSupport + "," + ulist[i].AcademicCapability  + ","+ collegeTable.name_cn.get(ulist[i].schoolName));
        }
        fw.close();
    }

    /****
     * 读取 OverallGlobal.csv 返回一个 UnivEntry List 包含 英文name and score
     * 
     * @return
     * @throws IOException
     */
    public static ArrayList<UnivEntry> parseList() throws IOException {
        File f = new File(overallGlobalFile);

        CSVReader csvReader = new CSVReader(new InputStreamReader(new FileInputStream(f), "UTF-8"));
        List<String[]> clist = csvReader.readAll();
        csvReader.close();
        if (clist == null || clist.size() == 0)
            return null;

        ArrayList<UnivEntry> ulist = new ArrayList<UnivEntry>();
        for (int i = 0; i < clist.size(); i++) {
            String[] entryString = clist.get(i);
            String entryName = entryString[1].trim();
            int score = Integer.parseInt(entryString[3]);
            UnivEntry entry = new UnivEntry(entryName, null, score);
            ulist.add(entry);
        }
        return ulist;
    }

}

class EndowmentComparator implements Comparator<UnivEntry> {
    DBpediaTable collegeTable;

    public EndowmentComparator(DBpediaTable collegeTable) {
        this.collegeTable = collegeTable;
    }

    public int compare(UnivEntry p1, UnivEntry p2) {
        double d1 = UnivRanking.getAverageEndowment(collegeTable, p1.schoolName);
        double d2 = UnivRanking.getAverageEndowment(collegeTable, p2.schoolName);
        return (int) (d2 - d1);
    }
}

class FacultyStudentRatioComparator implements Comparator<UnivEntry> {
    DBpediaTable collegeTable;

    public FacultyStudentRatioComparator(DBpediaTable collegeTable) {
        this.collegeTable = collegeTable;
    }

    public int compare(UnivEntry p1, UnivEntry p2) {
        double d1 = UnivRanking.getFacultyStudentRatio(collegeTable, p1.schoolName);
        double d2 = UnivRanking.getFacultyStudentRatio(collegeTable, p2.schoolName);
        if (d2 > d1)
            return 1;
        if (d2 < d1)
            return -1;
        return 0;
    }
}

class AlmaMaterComparator implements Comparator<UnivEntry> {
    HashMap<String, Double> almaMaterMap;

    public AlmaMaterComparator(HashMap<String, Double> almaMaterMap) {
        this.almaMaterMap = almaMaterMap;
    }

    public int compare(UnivEntry p1, UnivEntry p2) {
        Double d1 = almaMaterMap.get(p1.schoolName);
        if (d1 == null)
            d1 = 0.0;
        Double d2 = almaMaterMap.get(p2.schoolName);
        if (d2 == null)
            d2 = 0.0;
        if (d2 > d1)
            return 1;
        if (d2 < d1)
            return -1;
        return 0;
    }
}

class UniversityTwitterFansComparator implements Comparator<UnivEntry>{
    HashMap<String, Long> UniversityTwitter;
    public UniversityTwitterFansComparator(HashMap<String, Long> UniversityTwitter){
        this.UniversityTwitter = UniversityTwitter;
    }
    public int compare(UnivEntry o1, UnivEntry o2) {
        Long d1 = UniversityTwitter.get(o1.schoolName);
        Long d2 = UniversityTwitter.get(o2.schoolName);

        if (d2 > d1)
            return 1;
        if (d2 < d1)
            return -1;
        return 0;
    }
}
class UniversityTwitterFansRadioComparator implements Comparator<UnivEntry>{
    HashMap<String, Long> UniversityTwitter;
    public UniversityTwitterFansRadioComparator(HashMap<String, Long> UniversityTwitter){
        this.UniversityTwitter = UniversityTwitter;
    }
    public int compare(UnivEntry o1, UnivEntry o2) {
        Double d1 = UnivRanking.getRadio(UniversityTwitter.get(o1.schoolName),o1.schoolName);
        Double d2 = UnivRanking.getRadio(UniversityTwitter.get(o2.schoolName),o2.schoolName);
        if (d2 > d1)
            return 1;
        if (d2 < d1)
            return -1;
        return 0;
    }
}
class AlmaMaterRadioComparator implements Comparator<UnivEntry>{
    HashMap<String, Double> almaMaterMap;
    public AlmaMaterRadioComparator(HashMap<String, Double> almaMaterMap){
        this.almaMaterMap = almaMaterMap;
    }
    public int compare(UnivEntry o1, UnivEntry o2) {
        Double d1 = UnivRanking.getRadio(almaMaterMap.get(o1.schoolName),o1.schoolName);
        Double d2 = UnivRanking.getRadio(almaMaterMap.get(o2.schoolName),o2.schoolName);
        if (d2 > d1)
            return 1;
        if (d2 < d1)
            return -1;
        return 0;
    }
}
